﻿using System.Collections.Generic;

namespace SchemeFileSystem
{
    using System;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Text;

    using SchemeFileSystem.Providers;

    public class Scheme
    {
        private static readonly List<IFilesystem> filesystems = new List<IFilesystem>();
 
        public static void Init()
        {
            AddFileSystem<Providers.File>();
            AddFileSystem<Zip>();
            AddFileSystem<Chrome>();

            Map("fonts://", Environment.GetFolderPath(Environment.SpecialFolder.Fonts));
            Map("desktop://", Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
            Map("appdata://", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
            Map("documents://", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
            Map("videos://", Environment.GetFolderPath(Environment.SpecialFolder.MyVideos));
            Map("pictures://", Environment.GetFolderPath(Environment.SpecialFolder.MyPictures));
            Map("music://", Environment.GetFolderPath(Environment.SpecialFolder.MyMusic));
            Map("applications://", Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles));
            Map("computer://", Environment.GetFolderPath(Environment.SpecialFolder.MyComputer));
            Map("user://", Environment.GetFolderPath(Environment.SpecialFolder.UserProfile));
            Map("temp://", Path.GetTempPath());
        }

        public static void Map(string scheme, string path)
        {
            filesystems.Add(new MappedDrive(scheme, path));
        }

        public static void AddFileSystem<TFileSystem>()
            where TFileSystem : IFilesystem, new()
        {
            filesystems.Add(new TFileSystem());
        } 

        public static void CreateFolder(string path)
        {
            var fs = GetFileSystem(getScheme(path));
            fs.CreateFolder(path);
        }

        public static void CreateFile(string path, string content)
        {
            var fs = GetFileSystem(getScheme(path));
            fs.CreateFile(path, content);
        }

        public static void StoreFile(string path)
        {
            CreateFile(path, System.IO.File.ReadAllText(path));
        }

        public static string ReadFile(string path)
        {
            var fs = GetFileSystem(getScheme(path));
            return fs.ReadFile(path);
        }

        public static string[] GetFiles(string path)
        {
            var fs = GetFileSystem(getScheme(path));
            return fs.GetFiles(path);
        }

        public static string[] GetFolders(string path)
        {
            var fs = GetFileSystem(getScheme(path));
            return fs.GetFolders(path);
        }

        public static T Read<T>(string path) where T : class
        {
            if (typeof(T).Name == typeof(Image).Name)
            {
                var ms = new MemoryStream(Encoding.Default.GetBytes(ReadFile(path)));
                return Image.FromStream(ms) as T;
            }
            if (typeof(T).Name == typeof(string).Name)
            {
                return ReadFile(path) as T;
            }
            return ReadFile(path) as T;
        }

        private static string getScheme(string path)
        {
            var uri = new Uri(path);
            return uri.Scheme + "://";
        }

        public static IFilesystem GetFileSystem(string scheme)
        {
            return filesystems.FirstOrDefault(filesystem => filesystem.Schemes.Any(s => s == scheme));
        }

        public static void Mount(char letter, string path)
        {
            var fs = GetFileSystem(getScheme(path));
            fs.Mount(letter, path);
        }

        public static void Unmount(char letter, string path)
        {
            var fs = GetFileSystem(getScheme(path));
            fs.Unmount(letter, path);
        }
    }
}
